package com.ruoyi.collect.pressure.service;

import com.ruoyi.collect.pressure.model.CollectorPressureDto;
import com.ruoyi.collect.pressure.model.FileDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.TriConsumer;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public abstract class CollectParser {
    protected CollectorPressureDto mapper;
    protected Charset charset;
    // 备份目录
    private static final String BACKUP_DIR = "/home/deploy/backup";
//    private static final String BACKUP_DIR = "C:\\Users\\11138\\Desktop\\pressureCopy";
    private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    private static final String BACKUP_FILE_PATTERN = "yyyyMMdd_HHmmss";
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(BACKUP_FILE_PATTERN);

    public abstract void parse(List<FileDto> files);
    protected abstract String getFileNameRegex(final String type);

    protected void tryAnalyze(final Consumer<List<FileDto>> analyzer, final List<FileDto>
            FileDto) {
        long start = System.currentTimeMillis();
        try {
            log.info("start_try");
            analyzer.accept(FileDto);
        } catch (Exception e) {
            log.warn("analyze_exception", e);
        } finally {
            log.info("end_try: [{}]", System.currentTimeMillis() - start);
        }
    }

    protected List<String> getMatches(String string, final String regex) {
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(string);
        if (!matcher.matches()) {
            return Collections.emptyList();
        }

        List<String> matches = new ArrayList<>(matcher.groupCount());
        for (int i = 1; i <= matcher.groupCount(); i++) {
            matches.add(matcher.group(i));
        }
        return matches;
    }

    protected void analyze(final String type, final List<FileDto> collectFileInfos, final TriConsumer<List<String>, String, FileDto> analyze) {
        collectFileInfos.forEach(file -> {
            long start = System.currentTimeMillis();
            try {
                if (file.isAnalyzed()) {
                    log.info("analyzed:[{}]", file);
                    return;
                }
                List<String> matches = getMatches(file.getFileName(), getFileNameRegex(type));
                if (CollectionUtils.isEmpty(matches) || matches.size() != 2) {
                    log.debug("not_match: [{}]", file.getFileName());
                    return;
                }

                String content = new String(file.getBytes(), charset).replace("\ufeff", "");
                log.info("analyzing:[{}]", file);
                analyze.accept(matches, content, file);
                backupFile(file.getPath(),BACKUP_DIR);
                delete(file.getPath());
            } catch (Exception e) {
                log.warn("analyze_fail[{}]: [{}]", type, file);
                log.warn("", e);
            }
            log.info("analyze_[{}]: [{} - {}]", type, System.currentTimeMillis() - start, file.getPath());
        });
    }

    // 备份文件的方法
    private void backupFile(String sourcePath, String backupDir) throws IOException {
        File sourceFile = new File(sourcePath);
        String backupFileName = DATE_FORMAT.format(new Date()) + "_" + sourceFile.getName();
        Path backupPath = Paths.get(backupDir, backupFileName);
        Files.copy(sourceFile.toPath(), backupPath);
        startScheduledDeletion(backupDir);
        log.info("Backed up file to: {}", backupPath);
    }
    // 定时删除旧备份文件的方法
    public void startScheduledDeletion(String backupDir) {
        Runnable task = () -> {
            File backupDirFile = new File(backupDir);
            if (backupDirFile.exists() && backupDirFile.isDirectory()) {
                for (File file : backupDirFile.listFiles()) {
                    String fileName = file.getName();
                    if (fileName.matches("\\d{14}_.*")) { // 文件名格式是 "yyyyMMdd_HHmmss_originalFileName"
                        String timestampPart = fileName.substring(0, 14);
                        try {
                            Date backupDate = DATE_FORMAT.parse(timestampPart);
                            if (new Date().after(new Date(backupDate.getTime() + TimeUnit.DAYS.toMillis(1)))) {
                                // 如果备份文件是一天前的或更早的，则删除它
                                if (file.delete()) {
                                    log.info("Deleted old backup file: {}", file.getAbsolutePath());
                                } else {
                                    log.warn("Failed to delete old backup file: {}", file.getAbsolutePath());
                                }
                            }
                        } catch (Exception e) {
                            log.error("Error processing backup file: {}", file.getAbsolutePath(), e);
                        }
                    }
                }
            }
        };
        scheduler.scheduleAtFixedRate(task, 0, 24, TimeUnit.HOURS); // 每天凌晨开始检查并删除旧文件
    }


    private boolean delete(String filePath) throws InterruptedException {
        for (int i = 0; i < 2; i++) {
            boolean delete = new File(filePath).delete();
            if (delete) {
                return true;
            }
            if (!new File(filePath).exists()) {
                return true;
            }
            System.gc();
            Thread.sleep(10 * i);
            log.warn("delete_count: [{}]", i);
        }
        log.warn("delete_fail: [{}]", filePath);
        return false;
    }

    protected boolean isNotEnd(final String endTime) {
        return StringUtils.isEmpty(endTime) || "1900-01-01 00:00:00".equals(endTime);
    }
}
